﻿using IP2Region.Ex.Models;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR;
using MiniExcelLibs;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using Qiniu.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZhonTai.Admin.Core.Attributes;
using ZhonTai.Admin.Core.SignalR;
using ZhonTai.Admin.Tools.Cache;
using ZhonTai.Industry.Contracts.Core.Enums;
using ZhonTai.Industry.Contracts.Model.Entity;
using ZhonTai.Industry.Core.Consts;
using ZhonTai.Industry.Core.Core.Common;
using ZhonTai.Industry.Core.Tool;
using ZhonTai.Industry.Domain.ReworkDefectRecord;
using ZhonTai.Industry.Domain.WorkParamRecord;
using ZhonTai.Industry.Domain.WorkStationRecord;

namespace ZhonTai.Industry.Core.CraftGather.Save
{
    /// <summary>
    /// 保存操作
    /// </summary>
    [InjectTransient]
    public class SaveHandle : WorkExecuteBase
    {
        private readonly ICacheTool _cacheTool;
        private readonly IWorkParamRecordRepository _workParamRecordRepository;
        private readonly IWorkStationRecordRepository _stationRecordRepository;
        private readonly IReworkDefectRecordRepository _reworkDefectRecordRepository;
        private readonly IHubContext<MessageHub> _hub;

        public SaveHandle(
            ICacheTool cacheTool,
            IWorkParamRecordRepository workParamRecordRepository,
            IWorkStationRecordRepository stationRecordRepository,
            IReworkDefectRecordRepository reworkDefectRecordRepository,
            IHubContext<MessageHub> hub)
        {
            _cacheTool = cacheTool;
            _stationRecordRepository = stationRecordRepository;
            _workParamRecordRepository = workParamRecordRepository;
            _reworkDefectRecordRepository = reworkDefectRecordRepository;
            _hub = hub;
        }

        public override async Task ExecuteAsync(PushShip content)
        {
            try
            {
                //保存主条码
                string? masterCode = content.Example.TryGetValue<string>(OffsetConsts.QueryMasterCode);
                if (string.IsNullOrWhiteSpace(masterCode))
                {
                    var otherResult = await content.Example.WriteAsync(2, (short)SaveResultEnum.EmptyMasterCode);
                    if (otherResult.IsSuccess)
                    {
                        logger.Warn($"保存请求：工站【{content.OPCode}】条码不存在，回复【{SaveResultEnum.EmptyMasterCode}】写入成功！");
                    }
                    return;
                }

                string? stationCode = content.OPCode;
                //工站ID
                long stationId = content.StationId;
                //订单ID
                long? orderId = await _cacheTool.GetAsync<long?>(CacheKey.StationId);
                //产品型号ID
                long? productId = await _cacheTool.GetAsync<long?>(CacheKey.ProductId);
                //产品总状态
                short productStatus = content.Example.TryGetValue<short>(OffsetConsts.ProductStatus);
                //载体
                string? slot = content.Example.TryGetValue<string?>(OffsetConsts.Slot);
                //缺陷代码
                string? defectCode = content.Example.TryGetValue<string?>(OffsetConsts.DefectCode);
                //开始时间
                DateTime startTime = await _cacheTool.GetAsync<DateTime>(CacheKey.QueryStartTime + content.StationId);
                if (startTime == DateTime.MinValue)
                {
                    startTime = DateTime.Now;
                }
                //工艺参数集合
                List<DBField> param = content.Example._plcDB.DataFields.FindAll(f => f.GroupName == "Param");
                if (param.Count > 0)
                {
                    string paramDetail = string.Empty;
                    // 生成工艺参数记录列表
                    List<WorkParamRecordEntity> workParamList = new(param.Count);
                    List<WorkParamRecordEntity> workParamRecords = param.Select(field => new WorkParamRecordEntity
                    {
                        ProductCode = masterCode,
                        StationId = stationId,
                        OrderId = orderId,
                        ProductModelId = productId,
                        ParameterName = field.Description,
                        ParameterValue = content.Example.TryGetValue<string>(field.Another),
                        Unit = field.Unit,
                        Status = productStatus == 1 ? "OK" : "NG",
                        Upload = false
                    }).ToList();
                    workParamList.AddRange(workParamRecords);
                    paramDetail = string.Join(
                        "\n",
                        workParamList.Select(s => $"{s.ParameterName}:{s.ParameterValue}")
                    );
                    await _workParamRecordRepository.InsertAsync(workParamList);
                    _ = _hub.Clients.All.SendAsync(stationCode + "Details", paramDetail);
                }
                //保存过站信息
                var stationRecordEntity = new WorkStationRecordEntity
                {
                    ProductCode = masterCode,
                    StationId = stationId,
                    OrderId = orderId,
                    ProductModelId = productId,
                    ShiftId = 1,
                    StartTime = startTime,
                    EndTime = DateTime.Now,
                    CycleTime = (DateTime.Now - startTime).TotalSeconds,
                    Result = productStatus == 1 ? "OK" : "NG",
                    Slot = slot,
                    DefectCode = productStatus == 1 ? null : defectCode
                };
                //记录NG产品
                if (productStatus != (short)1)
                {
                    var reworkDefectRecordEntity = new ReworkDefectRecordEntity
                    {
                        ProductCode = masterCode,
                        DefectCode = defectCode == null ? null : defectCode,
                        FirstStationId = stationId,
                        FristStationCode = stationCode,
                        CurrentStatus = 1,
                        DetectionDate = DateTime.Now,
                    };
                    await _reworkDefectRecordRepository.InsertAsync(reworkDefectRecordEntity);
                }
                await _stationRecordRepository.InsertAsync(stationRecordEntity);

                if (stationId == 660776053911557)
                {
                    FtpExample ftpExample = new FtpExample(@"ftp://192.168.20.178", "User2", "123456", "FTPServer/" + "ST1");
                    ftpExample.DownloadLatestFile($@"D:\FTPClient\Product\{masterCode.Replace(":", "")}.xlsx");
                    await SaveImportDataAsync(masterCode, stationId, orderId, productId);
                }
                if (stationId == 660776070414341)
                {
                    FtpExample ftpExample = new FtpExample(@"ftp://192.168.20.178", "User2", "123456", "FTPServer/" + "ST2");
                    ftpExample.DownloadLatestFile($@"D:\FTPClient\Product\{masterCode.Replace(":", "")}.xlsx");
                    await SaveImportDataAsync(masterCode, stationId, orderId, productId);
                }
                var result = await content.Example.WriteAsync(2, (short)SaveResultEnum.Success);
                if (result.IsSuccess)
                {
                    logger.Info($"保存请求：条码：【{masterCode}】工站【{content.OPCode}】回复【{SaveResultEnum.Success}】写入成功!");
                }
            }
            catch (Exception ex)
            {
                var result = await content.Example.WriteAsync(2, (short)SaveResultEnum.Success);
                if (result.IsSuccess)
                {
                    logger.Error($"保存请求：工站【{content.OPCode}】程序保存错误，原因：{ex.Message},回复【{SaveResultEnum.Success}】成功!");
                }
            }
        }

        private async Task SaveImportDataAsync(string masterCode, long stationId, long? orderId, long? productId)
        {
            Dictionary<string, string> deviceDataDic = new Dictionary<string, string>();
            List<WorkParamRecordEntity> workParamList = new(24);
            var rows = MiniExcel.Query($"D:\\FTPClient\\Product\\{masterCode.Replace(":", "")}.xlsx").Take(14).ToList();
            //[mm]
            var Amplitude1 = DynamicToString(rows[12].B);
            deviceDataDic.Add(nameof(Amplitude1), Amplitude1);
            var Amplitude2 = DynamicToString(rows[13].B);
            deviceDataDic.Add(nameof(Amplitude2), Amplitude2);

            //[Hz]
            var Frequency1 = DynamicToString(rows[12].C);
            deviceDataDic.Add(nameof(Frequency1), Frequency1);

            var Frequency2 = DynamicToString(rows[13].C);
            deviceDataDic.Add(nameof(Frequency2), Frequency2);

            //[mm/s]
            var Velocity1 = DynamicToString(rows[12].D);
            deviceDataDic.Add(nameof(Velocity1), Velocity1);

            var Velocity2 = DynamicToString(rows[13].D);
            deviceDataDic.Add(nameof(Velocity2), Velocity2);

            //[N]
            var ReboundF1 = DynamicToString(rows[12].E);
            deviceDataDic.Add(nameof(ReboundF1), ReboundF1);

            var ReboundF2 = DynamicToString(rows[13].E);
            deviceDataDic.Add(nameof(ReboundF2), ReboundF2);

            //[N]
            var CompressF1 = DynamicToString(rows[12].F);
            deviceDataDic.Add(nameof(CompressF1), CompressF1);

            var CompressF2 = DynamicToString(rows[13].F);
            deviceDataDic.Add(nameof(CompressF2), CompressF2);

            //[N]
            var ReboundFUpperLimit1 = DynamicToString(rows[12].G);
            deviceDataDic.Add(nameof(ReboundFUpperLimit1), ReboundFUpperLimit1);

            var ReboundFUpperLimit2 = DynamicToString(rows[13].G);
            deviceDataDic.Add(nameof(ReboundFUpperLimit2), ReboundFUpperLimit2);

            //[N]
            var ReboundFLowerLimit1 = DynamicToString(rows[12].H);
            deviceDataDic.Add(nameof(ReboundFLowerLimit1), ReboundFLowerLimit1);

            var ReboundFLowerLimit2 = DynamicToString(rows[13].H);
            deviceDataDic.Add(nameof(ReboundFLowerLimit2), ReboundFLowerLimit2);

            //[N]
            var CompressFUpperLimit1 = DynamicToString(rows[12].I);
            deviceDataDic.Add(nameof(CompressFUpperLimit1), CompressFUpperLimit1);

            var CompressFUpperLimit2 = DynamicToString(rows[13].I);
            deviceDataDic.Add(nameof(CompressFUpperLimit2), CompressFUpperLimit2);

            //[N]
            var CompressFLowerLimit1 = DynamicToString(rows[12].J);
            deviceDataDic.Add(nameof(CompressFLowerLimit1), CompressFLowerLimit1);

            var CompressFLowerLimit2 = DynamicToString(rows[13].J);
            deviceDataDic.Add(nameof(CompressFLowerLimit2), ReboundFUpperLimit2);

            var ReboundFHL1 = DynamicToString(rows[12].K);
            deviceDataDic.Add(nameof(ReboundFHL1), ReboundFHL1);

            var ReboundFHL2 = DynamicToString(rows[13].K);
            deviceDataDic.Add(nameof(ReboundFHL2), ReboundFHL2);

            var CompressFHL1 = DynamicToString(rows[12].L);
            deviceDataDic.Add(nameof(CompressFHL1), CompressFHL1);

            var CompressFHL2 = DynamicToString(rows[13].L);
            deviceDataDic.Add(nameof(CompressFHL2), CompressFHL2);

            //[A]
            var AMPS1 = DynamicToString(rows[12].M);
            deviceDataDic.Add(nameof(AMPS1), AMPS1);

            var AMPS2 = DynamicToString(rows[13].M);
            deviceDataDic.Add(nameof(AMPS2), AMPS2);

            var Result1 = DynamicToString(rows[12].N);

            //保存工艺参数
            List<WorkParamRecordEntity>? workParamRecords = deviceDataDic.Select(field => new WorkParamRecordEntity
            {
                ProductCode = masterCode,
                StationId = stationId,
                OrderId = orderId,
                ProductModelId = productId,
                ParameterName = field.Key,
                ParameterValue = field.Value,
                Unit = "",
                UpperLimit = 0,
                LowerLimit = 0,
                Status = Result1 == "Pass" ? "OK" : "NG",
                Upload = false
            }).ToList();
            workParamList.AddRange(workParamRecords);
            await _workParamRecordRepository.InsertAsync(workParamList);
        }
    }
}